using System.Reflection;
using System.Security.Claims;
using KL.Standard.Model.Attribute;

namespace KL.Core.Common.Utils;

/// <summary>
/// ClaimUtils 工具
/// </summary>
public class ClaimUtils
{
    /// <summary>
    /// 将T实例中提取标签为ClaimConfigAttribute构建成一个ClaimsIdentity
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="entity"></param>
    /// <returns></returns>
    public static ClaimsIdentity CreateClaimInfos<T>(T entity)
    {
        var type = entity.GetType();
        List<Claim> list = new List<Claim>();
        type.GetProperties()
            .ToList()
            .ForEach(i =>
            {
                var attribute = i.GetCustomAttributes<ClaimConfigAttribute>().FirstOrDefault();
                if (attribute != null && attribute.IsUsed)
                {
                    var showName = string.IsNullOrEmpty(attribute.ShowName) ? i.Name : attribute.ShowName;
                    if (i.GetValue(entity) != null)
                        list.Add(new Claim(showName, i.GetValue(entity).ToString()));
                }
            });
        return new ClaimsIdentity(list.ToArray());
        //return null;
    }

    /// <summary>
    /// 从解析出来token转换T实例
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="User"></param>
    /// <returns></returns>
    public static T GetInfo4Claims<T>(ClaimsPrincipal User)
    {
        var resultUser = Activator.CreateInstance<T>();
        var type = resultUser.GetType();

        type.GetProperties()
            .ToList()
            .ForEach(i =>
            {
                var attribute = i.GetCustomAttributes<ClaimConfigAttribute>().FirstOrDefault();
                if (attribute != null && attribute.IsUsed)
                {
                    var showName = string.IsNullOrEmpty(attribute.ShowName) ? i.Name : attribute.ShowName;
                    if (!string.IsNullOrEmpty(User.FindFirst(d => d.Type == showName)?.Value))
                    {
                        switch (attribute.FieldType)
                        {
                            case "str":
                                i.SetValue(resultUser, User.FindFirst(d => d.Type == showName)?.Value);
                                break;
                            case "int":
                                i.SetValue(resultUser, Int32.Parse(User.FindFirst(d => d.Type == showName).Value));
                                break;
                            case "dt":
                                i.SetValue(resultUser, DateTime.Parse(User.FindFirst(d => d.Type == showName).Value));
                                break;
                            default:
                                break;

                        }
                    }
                    //i.SetValue(resultUser, User.FindFirst(d => d.Type == showName)?.Value);
                }
            });
        return resultUser;
    }

    /// <summary>
    /// 从解析出来token转换T实例
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="User"></param>
    /// <param name="resultUser"></param>
    /// <returns></returns>
    public static void GetInfo4Claims<T>(ClaimsPrincipal User, T resultUser)
    {
        //var resultUser = Activator.CreateInstance<T>();
        var type = resultUser.GetType();

        type.GetProperties()
            .ToList()
            .ForEach(i =>
            {
                var attribute = i.GetCustomAttributes<ClaimConfigAttribute>().FirstOrDefault();
                if (attribute != null && attribute.IsUsed)
                {
                    var showName = string.IsNullOrEmpty(attribute.ShowName) ? i.Name : attribute.ShowName;
                    if (!string.IsNullOrEmpty(User.FindFirst(d => d.Type == showName)?.Value))
                    {
                        switch (attribute.FieldType)
                        {
                            case "str":
                                i.SetValue(resultUser, User.FindFirst(d => d.Type == showName)?.Value);
                                break;
                            case "int":
                                i.SetValue(resultUser, Int32.Parse(User.FindFirst(d => d.Type == showName).Value));
                                break;
                            case "dt":
                                i.SetValue(resultUser, DateTime.Parse(User.FindFirst(d => d.Type == showName).Value));
                                break;
                            default:
                                break;

                        }
                    }
                    //i.SetValue(resultUser, User.FindFirst(d => d.Type == showName)?.Value);
                }
            });
        //return resultUser;
    }
}